package com.yj.auto.core.jfinal.context;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.jfinal.aop.Enhancer;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.IPlugin;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.yj.auto.core.base.annotation.Service;
import com.yj.auto.core.base.exception.AutoRuntimeException;
import com.yj.auto.core.jfinal.base.BaseCache;
import com.yj.auto.core.jfinal.base.BaseService;
import com.yj.auto.utils.ClassUtil;

/**
 * 加载Service实例
 */
public class AutoServiceConfig implements IPlugin {

	private static final Log log = Log.getLog(AutoServiceConfig.class);
	private List<String> includeJars = new ArrayList<String>();

	public void addJar(String jarName) {
		if (StrKit.notBlank(jarName)) {
			includeJars.add(jarName);
		}
	}

	/**
	 * 存放service实例
	 */
	private static final Map<String, BaseService> serviceMap = new HashMap<String, BaseService>();

	/**
	 * 获取service实例
	 * 
	 * @param serviceName
	 * @return
	 */
	public static BaseService getService(String serviceName) {
		return serviceMap.get(serviceName);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public boolean start() {
		// 1.扫描所有继承BaseService的类
		List<Class<? extends BaseService>> serviceClasses = ClassUtil.findInClasspathAndJars(BaseService.class, includeJars);
		serviceClasses.add(BaseService.class); // 加入BaseService本身

		// 2.循环处理Service实例化
		for (Class serviceCls : serviceClasses) {
			if (ClassUtil.isAbstract(serviceCls))
				continue;
			// 获取Service注解对象
			Service serviceBind = (Service) serviceCls.getAnnotation(Service.class);
			if (serviceBind == null) {
				throw new AutoRuntimeException(serviceCls.getName() + "继承了BaseService，但是没有注解绑定 ！");
			}

			// 获取Service注解属性
			String name = serviceBind.name().trim();
			if (name.equals("")) {
				throw new AutoRuntimeException(serviceCls.getName() + "注解错误，name不能为空 ！");
			}

			if (serviceMap.get(name) == null) {
				BaseService srv = null;
				// 是否需要对service中的所有方法开启事务管理
				if (serviceBind.tx()) {
					srv = (BaseService) Enhancer.enhance(serviceCls, Tx.class); // 是
				} else {
					try {
						srv = (BaseService) serviceCls.newInstance();
						if (srv instanceof BaseCache) {// 实现了缓存接口
							Enhancer.enhance(srv);
						}
					} catch (Exception e) {
						throw new AutoRuntimeException(serviceCls.getName() + "实例化错误 ！", e);
					}
				}
				if (null != srv) {
					serviceMap.put(name, srv);
					if (srv instanceof BaseCache) {
						new Thread(new LoadCache((BaseCache) srv)).start();
					}
					log.debug("Service.add： name = " + name + ", class = " + serviceCls.getName());
				}
			} else {
				throw new AutoRuntimeException(serviceCls.getName() + "注解错误，Service name重复注册 ！");
			}
		}

		// 循环处理Service相互注入
		for (Map.Entry<String, BaseService> entry : serviceMap.entrySet()) {
			String serviceName = entry.getKey();
			Class serviceClass = entry.getValue().getClass();
			BaseService myService = AutoServiceConfig.getService(serviceName);// 获取Service实例
			Field[] parentFields = serviceClass.getDeclaredFields();// 查找成员变量
			for (Field field : parentFields) {
				try {
					if (ClassUtil.isFinal(field))
						continue;
					field.setAccessible(true);
					String name = field.getName();
					if (BaseService.class.isAssignableFrom(field.getType())) {// 是否service类型成员变量
						BaseService targetService = AutoServiceConfig.getService(name);// 获取目标Service实例
						field.set(myService, targetService);// 注入目标service实例
					}
				} catch (Exception e) {
					throw new AutoRuntimeException(serviceClass.getName() + "注入" + field.getName() + "失败", e);
				} finally {
					field.setAccessible(false);
				}
			}
		}

		return true;
	}

	@Override
	public boolean stop() {
		return true;
	}

}

class LoadCache implements Runnable {
	BaseCache srv = null;

	LoadCache(BaseCache srv) {
		this.srv = srv;
	}

	public void run() {
		srv.loadCache();
	}
}